package com.lx.constant.segment.update;

import cn.hutool.core.util.StrUtil;
import com.lx.common.utils.CommonClassUtil;
import com.lx.constant.consts.CommonConstant;
import com.lx.constant.consts.SqlFormatConstant;
import com.lx.constant.enums.ConditionKeyWordEnum;
import com.lx.constant.segment.ChildConditionSegment;
import com.lx.constant.segment.Segment;
import com.lx.wrapper.AbstractWrapper;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.query.Query;

import javax.persistence.Column;
import javax.persistence.Id;
import java.lang.reflect.Field;

/**
 * 更新Set语句项
 *
 * @author lx
 * @create 2022/12/9 14:09
 **/
@Setter
@Getter
public class SetSegment extends ChildConditionSegment {

    /**
     * 更新的Set语句基础表达式
     */
    static final String UPDATE_SET_FORMAT = ConditionKeyWordEnum.EQ.getFormatEl();

    /**
     * 复杂条件拼接符号占位表达式
     */
    static final String COMPLEX_SEPERATOR_FORMAT = " %s ";

    /**
     * Lambda右列占位项语句对象
     */
    private Segment updateColumnSegment;

    /**
     * 待更新值
     */
    private Object columnValue;

    @Override
    public String convertSegmentToQL(AbstractWrapper parentWrapper, AbstractWrapper thisWrapper, boolean isHQL) {
        //1.Set列值, 2.汇总更新值
        String setColumnName = super.convertSegmentToQL(parentWrapper, thisWrapper, isHQL),
                gatherVal = gatherUpdateItem(thisWrapper, isHQL);

        if (StrUtil.isEmpty(setColumnName) || StrUtil.isEmpty(gatherVal)) {
            //过滤掉该语句拼接
            return CommonConstant.EMPTY;
        }

        return String.format(UPDATE_SET_FORMAT, setColumnName, gatherVal);
    }

    @Override
    public void setHibernateParamByQuery(boolean isHQL, Query query) {
        //子条件项设置
        super.setHibernateParamByQuery(isHQL, query);

        if (getChildConditionWrapper() == null) {
            query.setParameter(getHibernatePlaceholder(false), getColumnValue());
        }
    }

    @Override
    public String getColumnNameBySegment(boolean isHQL) {
        String originColumnName = super.getColumnNameBySegment(isHQL);
        if (StrUtil.isEmpty(originColumnName)) {
            return originColumnName;
        }
        if (!isHQL) {
            //SQL获取的列名则直接返回
            return originColumnName;
        }
        Field columnField = getColumnField();
        if (columnField == null) {
            return originColumnName;
        }
        //当HQL语句获取列名时, 可能需要特殊扩展
        Field idColumnField = CommonClassUtil.findAnnotationFieldFromClass(columnField.getType(), Id.class, Column.class);
        if (idColumnField == null) {
            return originColumnName;
        }
        return originColumnName + CommonConstant.POINT + idColumnField.getAnnotation(Column.class).name();
    }

    /**
     * 获取汇总后的更新子项值
     * 支持包含[待更新值]\[Lambda右列占位项语句对象]\[子条件项] ,当前仅支持 + 号拼接,后续可考虑用其他逻辑处理
     *
     * @param thisWrapper
     * @param isHQL
     * @return
     */
    private String gatherUpdateItem(AbstractWrapper thisWrapper, boolean isHQL) {
        //目前仅支持+号拼接
        String complexFormat = String.format(COMPLEX_SEPERATOR_FORMAT, CommonConstant.PLUS);

        StringBuilder gbd = new StringBuilder(64);

        String tmpVal;
        if (getUpdateColumnSegment() != null
                && StrUtil.isNotEmpty(tmpVal = getUpdateColumnSegment().convertSegmentToQL(null, thisWrapper, isHQL))) {
            //Lambda右列占位项语句对象(不能传入parentWrapper,此更新列理论上仅作用于当前wrapper)
            gbd.append(tmpVal).append(complexFormat);
        }
        if (getColumnValue() != null
                && StrUtil.isNotEmpty(tmpVal = getHibernatePlaceholder(true))) {
            //待更新值
            gbd.append(tmpVal).append(complexFormat);
        }
        if (getChildConditionWrapper() != null
                && StrUtil.isNotEmpty(tmpVal = String.format(SqlFormatConstant.PARENTHESES_FORMAT, getChildConditionWrapper().getCompleteQL(isHQL, thisWrapper)))) {
            //子条件项
            gbd.append(tmpVal).append(complexFormat);
        }
        //需要去除最后一个加号
        String s = gbd.toString();
        return s.endsWith(complexFormat) ? s.substring(0, s.length() - complexFormat.length()) : s;
    }

}
